import { marked } from 'marked'
import hljs from 'highlight.js'

/**
 * 代码高亮配置选项
 */
export interface HighlightOptions {
  /** 是否启用代码高亮 */
  enabled?: boolean
  /** CSS类前缀 */
  classPrefix?: string
  /** 是否启用语言自动检测 */
  autoDetect?: boolean
  /** 自动检测时的语言候选列表 */
  autoDetectLanguages?: string[]
  /** 降级处理的默认语言 */
  fallbackLanguage?: string
  /** 支持的编程语言列表 */
  supportedLanguages?: string[]
}

/**
 * Markdown渲染配置选项
 */
export interface MarkdownOptions {
  /** 是否启用代码高亮 */
  highlight?: boolean
  /** 代码高亮详细配置 */
  highlightOptions?: HighlightOptions
  /** 是否启用换行符转换 */
  breaks?: boolean
  /** 是否启用GitHub风格Markdown */
  gfm?: boolean
}

/**
 * 默认代码高亮配置
 */
const DEFAULT_HIGHLIGHT_OPTIONS: HighlightOptions = {
  enabled: true,
  classPrefix: 'hljs language-',
  autoDetect: true,
  autoDetectLanguages: [
    'javascript', 'typescript', 'python', 'java', 'cpp', 'c', 'csharp',
    'php', 'ruby', 'go', 'rust', 'swift', 'kotlin', 'scala',
    'html', 'css', 'scss', 'less', 'xml', 'json', 'yaml',
    'sql', 'bash', 'shell', 'powershell', 'dockerfile',
    'markdown', 'plaintext'
  ],
  fallbackLanguage: 'plaintext',
  supportedLanguages: [
    // Web 开发
    'javascript', 'js', 'typescript', 'ts', 'html', 'css', 'scss', 'sass', 'less',
    'vue', 'react', 'angular', 'svelte', 'json', 'xml', 'yaml', 'yml',

    // 后端语言
    'python', 'py', 'java', 'cpp', 'c++', 'c', 'csharp', 'cs',
    'php', 'ruby', 'rb', 'go', 'rust', 'rs', 'swift', 'kotlin', 'kt', 'scala',

    // 脚本和配置
    'bash', 'sh', 'shell', 'powershell', 'ps1', 'batch', 'cmd',
    'dockerfile', 'docker', 'nginx', 'apache',

    // 数据库
    'sql', 'mysql', 'postgresql', 'sqlite', 'mongodb',

    // 其他
    'markdown', 'md', 'latex', 'tex', 'r', 'matlab', 'octave',
    'plaintext', 'text', 'txt'
  ]
}

/**
 * 默认Markdown配置
 */
const DEFAULT_OPTIONS: MarkdownOptions = {
  highlight: true,
  highlightOptions: DEFAULT_HIGHLIGHT_OPTIONS,
  breaks: true,
  gfm: true
}

/**
 * 配置marked解析器选项
 * @param options 自定义配置选项
 */
export function configureMarked(options: MarkdownOptions = {}): void {
  const config = { ...DEFAULT_OPTIONS, ...options }
  const highlightConfig = { ...DEFAULT_HIGHLIGHT_OPTIONS, ...config.highlightOptions }

  try {
    // 配置基础选项
    const markedOptions: any = {
      breaks: config.breaks,
      gfm: config.gfm
    }

    // 配置代码高亮渲染器
    if (config.highlight && highlightConfig.enabled) {
      const renderer = new marked.Renderer()

      // 重写代码块渲染方法
      renderer.code = ({ text, lang }: { text: string; lang?: string }) => {
        return renderCodeBlock(text, lang, highlightConfig)
      }

      // 重写行内代码渲染方法
      renderer.codespan = ({ text }: { text: string }) => {
        return `<code class="hljs-inline">${escapeHtml(text)}</code>`
      }

      // 应用自定义渲染器
      markedOptions.renderer = renderer
    } else {
      // 禁用代码高亮时，使用默认渲染器
      markedOptions.renderer = new marked.Renderer()
    }

    marked.setOptions(markedOptions)
  } catch (error) {
    console.error('配置marked解析器失败:', error)
    throw new Error('Markdown解析器配置失败')
  }
}

/**
 * 渲染代码块
 * @param text 代码内容
 * @param lang 指定的语言
 * @param options 高亮配置选项
 * @returns 渲染后的HTML
 */
function renderCodeBlock(text: string, lang: string | undefined, options: HighlightOptions): string {
  try {
    let highlightedCode = text
    let actualLanguage = lang || options.fallbackLanguage || 'plaintext'

    // 标准化语言名称
    const normalizedLang = normalizeLanguageName(lang)

    if (normalizedLang && isLanguageSupported(normalizedLang, options)) {
      // 使用指定的语言进行高亮
      if (hljs.getLanguage(normalizedLang)) {
        const result = hljs.highlight(text, { language: normalizedLang })
        highlightedCode = result.value
        actualLanguage = normalizedLang
      } else {
        // 指定的语言不被highlight.js支持，尝试自动检测
        const autoResult = performAutoDetection(text, options)
        highlightedCode = autoResult.code
        actualLanguage = autoResult.language
      }
    } else if (options.autoDetect) {
      // 自动检测语言
      const autoResult = performAutoDetection(text, options)
      highlightedCode = autoResult.code
      actualLanguage = autoResult.language
    } else {
      // 不进行高亮，使用纯文本
      highlightedCode = escapeHtml(text)
      actualLanguage = options.fallbackLanguage || 'plaintext'
    }

    // 生成CSS类名
    const cssClass = `${options.classPrefix}${actualLanguage}`

    return `<pre><code class="${cssClass}">${highlightedCode}</code></pre>`
  } catch (error) {
    console.warn('代码高亮失败:', error)
    // 高亮失败时返回原始代码
    return `<pre><code class="hljs">${escapeHtml(text)}</code></pre>`
  }
}

/**
 * 执行语言自动检测
 * @param text 代码内容
 * @param options 高亮配置选项
 * @returns 检测结果
 */
function performAutoDetection(text: string, options: HighlightOptions): { code: string; language: string } {
  try {
    let result

    if (options.autoDetectLanguages && options.autoDetectLanguages.length > 0) {
      // 使用指定的语言候选列表进行检测
      result = hljs.highlightAuto(text, options.autoDetectLanguages)
    } else {
      // 使用所有支持的语言进行检测
      result = hljs.highlightAuto(text)
    }

    // 检查检测结果的可信度
    const minRelevance = 5 // 最小相关性阈值
    if (result.relevance >= minRelevance && result.language) {
      return {
        code: result.value,
        language: result.language
      }
    } else {
      // 检测结果不可信，使用降级处理
      return {
        code: escapeHtml(text),
        language: options.fallbackLanguage || 'plaintext'
      }
    }
  } catch (error) {
    console.warn('语言自动检测失败:', error)
    return {
      code: escapeHtml(text),
      language: options.fallbackLanguage || 'plaintext'
    }
  }
}

/**
 * 标准化语言名称
 * @param lang 原始语言名称
 * @returns 标准化后的语言名称
 */
function normalizeLanguageName(lang: string | undefined): string | undefined {
  if (!lang) return undefined

  const langMap: Record<string, string> = {
    // JavaScript 相关
    'js': 'javascript',
    'jsx': 'javascript',
    'ts': 'typescript',
    'tsx': 'typescript',

    // Python 相关
    'py': 'python',
    'python3': 'python',

    // C/C++ 相关
    'c++': 'cpp',
    'cxx': 'cpp',
    'cc': 'cpp',

    // C# 相关
    'cs': 'csharp',
    'c#': 'csharp',

    // Shell 相关
    'sh': 'bash',
    'shell': 'bash',
    'zsh': 'bash',

    // 配置文件
    'yml': 'yaml',
    'dockerfile': 'docker',

    // 其他
    'md': 'markdown',
    'rb': 'ruby',
    'rs': 'rust',
    'kt': 'kotlin',
    'txt': 'plaintext',
    'text': 'plaintext'
  }

  const normalized = lang.toLowerCase().trim()
  return langMap[normalized] || normalized
}

/**
 * 检查语言是否被支持
 * @param lang 语言名称
 * @param options 高亮配置选项
 * @returns 是否支持
 */
function isLanguageSupported(lang: string, options: HighlightOptions): boolean {
  if (!options.supportedLanguages) return true

  return options.supportedLanguages.includes(lang.toLowerCase())
}

/**
 * 获取支持的语言列表
 * @returns 支持的语言列表
 */
export function getSupportedLanguages(): string[] {
  return [...DEFAULT_HIGHLIGHT_OPTIONS.supportedLanguages!]
}

/**
 * 检查特定语言是否被highlight.js支持
 * @param lang 语言名称
 * @returns 是否支持
 */
export function isHighlightJsLanguageSupported(lang: string): boolean {
  try {
    return Boolean(hljs.getLanguage(lang))
  } catch {
    return false
  }
}

/**
 * 获取highlight.js支持的所有语言
 * @returns 语言列表
 */
export function getHighlightJsSupportedLanguages(): string[] {
  return hljs.listLanguages()
}

/**
 * 渲染Markdown内容为HTML
 * @param content Markdown内容
 * @param options 渲染选项
 * @returns 渲染后的HTML字符串
 */
export function renderMarkdown(content: string, options: MarkdownOptions = {}): string {
  if (!content || typeof content !== 'string') {
    return ''
  }

  try {
    // 确保marked已正确配置
    configureMarked(options)

    // 渲染Markdown内容
    const html = marked(content)

    if (typeof html !== 'string') {
      throw new Error('Markdown渲染结果不是字符串')
    }

    return html
  } catch (error) {
    console.error('Markdown渲染失败:', error)
    // 渲染失败时返回原始内容，确保用户能看到内容
    return `<pre>${escapeHtml(content)}</pre>`
  }
}

/**
 * 转义HTML特殊字符
 * @param text 需要转义的文本
 * @returns 转义后的文本
 */
function escapeHtml(text: string): string {
  if (typeof document !== 'undefined') {
    const div = document.createElement('div')
    div.textContent = text
    return div.innerHTML
  }

  // 服务端渲染或测试环境的降级处理
  return text
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;')
}

/**
 * 清理HTML标签，返回纯文本
 * @param html HTML字符串
 * @returns 纯文本内容
 */
export function stripHtml(html: string): string {
  if (!html || typeof html !== 'string') {
    return ''
  }

  try {
    if (typeof document !== 'undefined') {
      // 浏览器环境：创建临时DOM元素来提取文本内容
      const div = document.createElement('div')
      div.innerHTML = html
      return div.textContent || div.innerText || ''
    }

    // 服务端渲染或测试环境：使用正则表达式清理
    return html.replace(/<[^>]*>/g, '')
  } catch (error) {
    console.error('HTML标签清理失败:', error)
    // 清理失败时使用正则表达式简单清理
    return html.replace(/<[^>]*>/g, '')
  }
}

/**
 * 检查内容是否包含Markdown语法
 * @param content 待检查的内容
 * @returns 是否包含Markdown语法
 */
export function hasMarkdownSyntax(content: string): boolean {
  if (!content || typeof content !== 'string') {
    return false
  }

  // 检查常见的Markdown语法模式
  const markdownPatterns = [
    /^#{1,6}\s+/m,           // 标题
    /\*\*.*?\*\*/,           // 粗体
    /\*.*?\*/,               // 斜体
    /`.*?`/,                 // 行内代码
    /```[\s\S]*?```/,        // 代码块
    /^\s*[-*+]\s+/m,         // 无序列表
    /^\s*\d+\.\s+/m,         // 有序列表
    /^\s*>\s+/m,             // 引用
    /\[.*?\]\(.*?\)/,        // 链接
    /!\[.*?\]\(.*?\)/,       // 图片
    /^\s*\|.*\|.*$/m,        // 表格
    /^---+$/m                // 分割线
  ]

  return markdownPatterns.some(pattern => pattern.test(content))
}

/**
 * 获取Markdown渲染统计信息
 */
export interface MarkdownStats {
  /** 字符数 */
  characters: number
  /** 行数 */
  lines: number
  /** 代码块数量 */
  codeBlocks: number
  /** 标题数量 */
  headings: number
  /** 链接数量 */
  links: number
  /** Think标签数量 */
  thinkTags: number
}

/**
 * 获取Markdown内容的统计信息
 * @param content Markdown内容
 * @returns 统计信息
 */
export function getMarkdownStats(content: string): MarkdownStats {
  if (!content || typeof content !== 'string') {
    return {
      characters: 0,
      lines: 0,
      codeBlocks: 0,
      headings: 0,
      links: 0,
      thinkTags: 0
    }
  }

  const lines = content.split('\n')
  const codeBlocks = (content.match(/```[\s\S]*?```/g) || []).length
  const headings = (content.match(/^#{1,6}\s+/gm) || []).length
  const links = (content.match(/\[.*?\]\(.*?\)/g) || []).length
  const thinkTags = (content.match(/<think>[\s\S]*?<\/think>/gi) || []).length

  return {
    characters: content.length,
    lines: lines.length,
    codeBlocks,
    headings,
    links,
    thinkTags
  }
}

/**
 * Think标签处理结果
 */
export interface ThinkTagResult {
  /** 处理后的HTML内容 */
  html: string
  /** 是否包含Think标签 */
  hasThinkTags: boolean
  /** Think标签数量 */
  thinkTagCount: number
}

/**
 * 处理Think标签和Markdown渲染
 * @param content 包含Think标签的原始内容
 * @param options Markdown渲染选项
 * @returns 处理结果
 */
export function processThinkTags(content: string, options: MarkdownOptions = {}): ThinkTagResult {
  if (!content || typeof content !== 'string') {
    return {
      html: '',
      hasThinkTags: false,
      thinkTagCount: 0
    }
  }

  try {
    // 检查是否包含Think标签
    const thinkTagRegex = /<think>([\s\S]*?)<\/think>/gi
    const thinkMatches = content.match(thinkTagRegex)
    const hasThinkTags = Boolean(thinkMatches)
    const thinkTagCount = thinkMatches ? thinkMatches.length : 0

    if (!hasThinkTags) {
      // 没有Think标签，直接渲染Markdown
      return {
        html: renderMarkdown(content, options),
        hasThinkTags: false,
        thinkTagCount: 0
      }
    }

    // 处理Think标签内容
    const processedContent = content.replace(thinkTagRegex, (match, thinkContent) => {
      try {
        // 清理Think标签内容的首尾空白
        const cleanThinkContent = thinkContent.trim()

        if (!cleanThinkContent) {
          // 空的Think标签
          return '<div class="think-tag think-empty"></div>'
        }

        // 渲染Think标签内的Markdown内容
        const renderedThinkContent = renderMarkdown(cleanThinkContent, options)

        // 包装Think标签内容，应用特殊样式
        return `<div class="think-tag">
          <div class="think-content">
            ${renderedThinkContent}
          </div>
        </div>`
      } catch (error) {
        console.warn('Think标签内容处理失败:', error)
        // 处理失败时返回原始内容，但仍应用Think样式
        return `<div class="think-tag think-error">
          <div class="think-content">
            <pre>${escapeHtml(thinkContent)}</pre>
          </div>
        </div>`
      }
    })

    // 渲染剩余的Markdown内容（Think标签外的内容）
    const finalHtml = renderMarkdown(processedContent, options)

    return {
      html: finalHtml,
      hasThinkTags: true,
      thinkTagCount
    }
  } catch (error) {
    console.error('Think标签处理失败:', error)
    // 处理失败时降级到普通Markdown渲染
    return {
      html: renderMarkdown(content, options),
      hasThinkTags: false,
      thinkTagCount: 0
    }
  }
}

/**
 * 检查内容是否包含Think标签
 * @param content 待检查的内容
 * @returns 是否包含Think标签
 */
export function hasThinkTags(content: string): boolean {
  if (!content || typeof content !== 'string') {
    return false
  }

  const thinkTagRegex = /<think>[\s\S]*?<\/think>/i
  return thinkTagRegex.test(content)
}

/**
 * 提取Think标签内容
 * @param content 包含Think标签的内容
 * @returns Think标签内容数组
 */
export function extractThinkTagContent(content: string): string[] {
  if (!content || typeof content !== 'string') {
    return []
  }

  const thinkTagRegex = /<think>([\s\S]*?)<\/think>/gi
  const matches = []
  let match

  while ((match = thinkTagRegex.exec(content)) !== null) {
    matches.push(match[1].trim())
  }

  return matches
}

/**
 * 移除Think标签，保留内容
 * @param content 包含Think标签的内容
 * @returns 移除Think标签后的内容
 */
export function removeThinkTags(content: string): string {
  if (!content || typeof content !== 'string') {
    return ''
  }

  try {
    // 移除Think标签，保留内容
    return content.replace(/<think>([\s\S]*?)<\/think>/gi, '$1')
  } catch (error) {
    console.error('移除Think标签失败:', error)
    return content
  }
}

// 初始化默认配置
configureMarked()
